<!DOCTYPE html>
<html>

<head>
<title>Cindy JS Example</title>
<!--Adapted from http://science-to-touch.com/CJS/CindyJS/complexFunctions/04_Explorer.html -->
<meta charset="UTF-8">
<script type="text/javascript" src="../../build/js/Cindy.js"></script>
<script type="text/javascript" src="../../build/js/CindyGL.js"></script>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>

<script id="csinit" type="text/x-cindyscript">
f(z, a, b, c, d, e, A, B, C, D) := z^5-A^5;

grid1=true;
grid2=true;
linear=false;
bw=false;
webcam=false;
camvideo=(;);
iscam=false;

t0 = seconds();
</script>
<script id="csdraw" type="text/x-cindyscript">
//UI

x=S.x;
if(x<S1.x,x=S1.x);
if(x>S2.x,x=S2.x);
S.xy=(x,S1.y);
speed=(S.x-S1.x)/2;

x=R.x;
if(x<R1.x,x=R1.x);
if(x>R2.x,x=R2.x);
R.xy=(x,R1.y);

x=T.x;
if(x<T1.x,x=T1.x);
if(x>T2.x,x=T2.x);
T.xy=(x,T1.y);

drawimage(S2+(0.04,-.06),S2+(0.13,0)+(0.04,-.06),"Rot");
drawimage(T2+(0.04,-.03),T2+(0.13,0)+(0.04,-.03),"Sat");
drawimage(R2+(0.04,-.04),R2+(0.13,0)+(0.04,-.04),"Grid");

sat = |T,T1|/|T2,T1|;
grid = round(|R,R1|/|R2,R1|*20);

//translate((1.6,0));
apply(-5..5,i,
  draw((i*.1+1.6,-.02),(i*.1+1.6,.02),color->(0,0,0),size->if(i==0,2,.5));
  if(i==0,draw((-.5+1.6,i*.1),(.5+1.6,i*.1),color->(0,0,0),size->2));
);
//translate((-1.6,0));
x=E.x;
if(x<1.1,x=1.1);
if(x>2.1,x=2.1);
E.xy=(x,0);
xx=round((E.x-1.2)*10);
xx=(E.x-1.6)*2;
yy=0;


if(A.x>1,A.size=6;drawtext(A+(.03,.03),"A"),A.size=4);
if(B.x>1,B.size=6;drawtext(B+(.03,.03),"B"),B.size=4);
if(C.x>1,C.size=6;drawtext(C+(.03,.03),"C"),C.size=4);
if(D.x>1,D.size=6;drawtext(D+(.03,.03),"D"),D.size=4);

drawtext((1.1,.8),"Variables for formula:",size->18);
drawtext((1.1,.7),"a=z-A, b=z-B, c=z-C, d=z-D, e",size->18);

drawtext(E+(.03,.03),"e");
drawtext((1,E.y)+(.05,-.1),"-1");
drawtext((1,E.y)+(1.08,-.1),"+1");



//PLOT


hsvToRGB(h, s, v) := (
  regional(j, p, q, t, f);

  h = (h-floor(h))*6;

  j = floor(h);
  f = h - j;

  p = 1 - s;
  q = 1 - s*f;
  t = 1 - s*(1-f);

  if(j == 0, [1, t, p],
  if(j == 1, [q, 1, p],
  if(j == 2, [p, 1, t],
  if(j == 3, [p, q, 1],
  if(j == 4, [t, p, 1],
  if(j == 5, [1, p, q]))))))*v
);


time = t0-seconds();

if (webcam & isundefined(camvideo), camvideo=cameravideo());
if (webcam & imageready(camvideo), (
  if (!iscam, iscam=true; err("webcam on"););
  color(z) := ( //what color should be given to a complex number z?
    z = if(linear, z/5, log(z));
    z = z * (grid+1);
    c = imagergb([-.2,0],[1.2,0],camvideo, mod(z/2/pi + .5+0.5*i, 1+1*i));
    b = c*[1,1,1]/3;
    sat*c + (1-sat)*[b,b,b]
  );
), (
  if (iscam, iscam=false; err("webcam off"););
color(z) := ( //what color should be given to a complex number z?
  regional(n, grey1, grey2);

  n = 2*grid*if(bw, .5, 1)*if(linear, .5, 1);
  z = if(!linear, log(z), 2*i*z)/2/pi + i*time*speed;

  zfract = n*z - floor(n*z); //value of n*z in C mod Z[i]

  grey1 = if(grid1 & n>0, im(zfract), 1);
  grey2 = if(grid2 & n>0, re(zfract), 1);

  if(bw,
    grey1 = if(grey1<0.5, 1, -1);
    grey2 = if(grey2<0.5, 1, -1);
  );

  hsvToRGB(im(z), if(bw, 0, sat), .5+.5*if(bw, grey1*grey2, re(sqrt(grey1*grey2))))
);
));

colorplot(
  regional(z, ac, bc, cc, dc);

  z = complex(#)*1.2;
  ac = complex(A)*1.2;
  bc = complex(B)*1.2;
  cc = complex(C)*1.2;
  dc = complex(D)*1.2;

  fval = f(z, z-ac, z-bc, z-cc, z-dc, xx, ac, bc, cc, dc);

  color(fval),
  (-1,-1), (1,1)
);

draw((1,-1),(1,1), color->(0,0,0), size->2);

</script>
<script type="text/javascript">

var cdy = CindyJS({
  ports: [{
    id: "CSCanvas",
      width: 820,
      height: 500,
      transform: [ { visibleRect: [-1, -1, 2.2, 1] } ]
  }],
  scripts: "cs*",
  geometry: [
    {name:"A", type:"Free", pos:[.8,0.1],color:[1,0,0],pinned:false,size:4},
    {name:"B", type:"Free", pos:[1.4,0.3],color:[0,1,0],pinned:false,size:4},
    {name:"C", type:"Free", pos:[1.6,0.3],color:[0,0,1],pinned:false,size:4},
    {name:"D", type:"Free", pos:[1.8,0.3],color:[1,1,0],pinned:false,size:4},
    {name:"E", type:"Free", pos:[1.7,0],color:[1,1,1],pinned:false,size:6},
    {name:"S1", type:"Free", pos:[1.2,-.8],color:[0,0,0],pinned:true,size:2},
    {name:"S2", type:"Free", pos:[2.0,-.8],color:[0,0,0],pinned:true,size:2},
    {name:"S", type:"Free", pos:[1.201,-.8],color:[1,1,1],pinned:false,size:4},
    {name:"l", type:"Segment", args:["S1","S2"],color:[0,0,0],pinned:false,size:2},
    {name:"R1", type:"Free", pos:[1.2,-.6],color:[0,0,0],pinned:true,size:2},
    {name:"R2", type:"Free", pos:[2.0,-.6],color:[0,0,0],pinned:true,size:2},
    {name:"R", type:"Free", pos:[1.7,-.6],color:[1,1,1],pinned:false,size:4},
    {name:"m", type:"Segment", args:["R1","R2"],color:[0,0,0],pinned:false,size:2},
    {name:"T1", type:"Free", pos:[1.2,-.4],color:[0,0,0],pinned:true,size:2},
    {name:"T2", type:"Free", pos:[1.99,-.4],color:[0,0,0],pinned:true,size:2},
    {name:"T", type:"Free", pos:[2.0,-.4],color:[1,1,1],pinned:false,size:4},
    {name:"o", type:"Segment", args:["T1","T2"],color:[0,0,0],pinned:false,size:2}
  ],
  animation: {autoplay: true},
  //transform:[{translate:[0,0]},{scale:10}],
  images:{Rot:"uiImages/Rot.png",Sat:"uiImages/SSat.png",Grid:"uiImages/Grid.png"},
  use: ["CindyGL"]
});
</script>
</head>

<body style="font-family:Arial;">

  <h1>Function Explorer</h1>
<div  style="width:800px; line-height: 1.5">
Here you can freely explore phase portraits of complex functions.
Variables accessible in the freely editable formula are $z$, $A$, $B$, $C$, $D$, $a$, $b$, $c$ ,$d$, $e$.
The complex number $z$ is the location in the image.
The variables $a,b,c,d$ depend on the position of the colored points
$A,B,C,D$. The dependence is
\[
a=z-A,
b=z-B,
c=z-C,
d=z-D.
\]
Varable $e$ is a real scalar that can be adjusted
between $-1$ and $+1$.

<br>
<br>

</div>

  <div id="CSCanvas" style="border:2px solid black"></div>
<div>
  <input id="ch1" onclick="cdy.evokeCS('grid1 = ' + this.checked);" checked type="checkbox" >angles&nbsp;&nbsp;&nbsp;
  <input id="ch2" onclick="cdy.evokeCS('grid2 = ' + this.checked);" checked type="checkbox" >radii&nbsp;&nbsp;&nbsp;
  <input id="ch3" onclick="cdy.evokeCS('linear = ' + this.checked);" type="checkbox" >linear diagram&nbsp;&nbsp;&nbsp;
  <input id="ch4" onclick="cdy.evokeCS('bw = ' + this.checked);" type="checkbox" >black/white&nbsp;&nbsp;&nbsp;
  <input id="ch5" onclick="cdy.evokeCS('webcam = ' + this.checked);
    document.getElementById('ch1').disabled =
    document.getElementById('ch2').disabled =
    document.getElementById('ch4').disabled = this.checked;" type="checkbox" >webcam<br>
  </div>
<div>
<input type="text" id="inp" value="z^5-A^5"  onkeypress="if((event.which ? event.which : event.keyCode)==13) { cdy.evokeCS('f(z, a, b, c, d, e, A, B, C, D) := (' + this.value + ');'); }" size="60" style="font-size:18px">
<select id="sel" onchange="document.getElementById('inp').value = this.value; cdy.evokeCS('f(z, a, b, c, d, e, A, B, C, D) := (' + this.value + ');');" style="width:20em;">
  <option>z^5-A^5</option>
  <option>(1-a)*(1+a)</option>
  <option>(z-A)/(z-B)</option>
  <option>z^(1+i)</option>
  <option>z^A</option>
  <option>(sin(3*a)/sin(3*b))^(1+i)</option>
  <option value="repeat(7, z = z*z + A)">Julia set</option>
  <option value="z = 0; repeat(11, z = z*z + a; z = z/abs(z)*min(abs(z),10))">Mandelbrot set</option>
  <option value="(1-z^(20*e))/(1-z)">Convergence of Geometric series</option>
  <option value="repeat(5, z = z - (z^3-A)/(3*z^2))">Newton</option>
  <option value="z=a; repeat(11, z = z - (z^3-b*c*d)/(3*z^2))">Newton-like</option>
</select>
</div>
</body>

</html>
